package com.action;

import cn.hutool.core.codec.Base64;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.bean.ResponseBean;
import com.pojo.*;
import com.service.*;
import com.util.DESUtil;
import com.util.IPUtil;
import com.util.JwtUtil;
import com.util.StringUtil;
import net.sf.json.JSONObject;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.ResponseBody;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/zhuji")
public class ZhujiAction {

    @Autowired
    private ZhujiService zhujiService;
    @Autowired
    private AppAdminService appAdminService;
    @Autowired
    private AreaService areaService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private VpnPeizhiService vpnPeizhiService;
    @Autowired
    private IpService ipService;
    @Value("${guonei_url}")
    private String guonei_url;
    @Value("${guowai_url}")
    private String guowai_url;
    @Value("${host}")
    private String host;
    /**
     * 分页查询主机
     * @param name  关键字
     * @param status  状态(0为禁用，1为启用)
     * @param page  页面
     * @param limit  条数
     * @return
     */
    @RequestMapping("/selectzhuji")
    @ResponseBody
    public ResponseBean selectzhuji(String name, String status, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int limit){
        IPage iPage = zhujiService.selectzhuji(page,limit,name,status);
        return new ResponseBean(0,iPage.getTotal(),"查询成功",iPage.getRecords());
    }

    /**
     * 新增主机
     * @param  zhuji   主机
     * @return
     */
    @RequestMapping("/addZhuji")
    public ResponseBean addZhuji(@RequestBody Zhuji zhuji, HttpServletRequest request){

        if(StringUtil.isNull(zhuji.getRemarks())){
            return new ResponseBean(1,1,"主机别名不能为空","");
        }else {
            if (!zhuji.getRemarks().matches("[0-9A-Za-z]*")) {
                return new ResponseBean(1,1,"主机别名不能含有中文和怪字符","");
            }
        }
        if(StringUtil.isNull(zhuji.getAddress())){
            return new ResponseBean(1,1,"主机地址不能为空","");
        }
        if(StringUtil.isNull(zhuji.getPort())){
            return new ResponseBean(1,1,"主机端口不能为空","");
        }
        if(StringUtil.isNull(zhuji.getUid())){
            return new ResponseBean(1,1,"主机用户ID不能为空","");
        }
        if(StringUtil.isNull(zhuji.getOut_id())){
            return new ResponseBean(1,1,"主机额外ID不能为空","");
        }
        if(StringUtil.isNull(zhuji.getCountry_id())){
            return new ResponseBean(1,1,"所属国家不能为空","");
        }
        if(StringUtil.isNull(zhuji.getArea_id())){
            return new ResponseBean(1,1,"所属区域不能为空","");
        }
        if(zhuji.getType() == null){
            zhuji.setType(2);
        }
        if(zhuji.getLianjie_num()==null){
            zhuji.setLianjie_num(0);
        }
        zhuji.setStatus(0);
        zhuji.setSy_lianjie_num(0);
        Admin admin = (Admin) request.getSession().getAttribute("admin");
        if (admin != null){
            zhuji.setAdmin_id(admin.getId());
        }
        if(zhujiService.save(zhuji)){
            return new ResponseBean(0,1,"操作成功","");
        }
        return new ResponseBean(1,1,"操作失败","");
    }
    /**
     * 修改主机状态
     * @param id   主机id
     * @param status   主机状态（0为禁用，1为启用）
     */
    @RequestMapping("/upStatus")
    public ResponseBean changeStatus(String id,Integer status) {
        Zhuji zhuji = new Zhuji();
        zhuji.setId(id);
        zhuji.setStatus(status);
        if(zhujiService.updateById(zhuji)){
            return new ResponseBean(0,1,"修改状态成功");
        }
        return new ResponseBean(1,1,"修改状态失败");
    }

    /**
     * 修改主机
     * @param zhuji  主机
     * @return
     */
    @RequestMapping("/updateZhuji")
    public ResponseBean updateZhuji(@RequestBody Zhuji zhuji) {

        Zhuji zhuji2 = zhujiService.getById(zhuji.getId());
        if(zhuji2 == null){
            return new ResponseBean(1,1,"未找到该主机","");
        }
        if(StringUtil.isNull(zhuji.getRemarks())){
            return new ResponseBean(1,1,"主机别名不能为空","");
        }else {
            if (!zhuji.getRemarks().matches("[0-9A-Za-z]*")) {
                return new ResponseBean(1,1,"主机别名不能含有中文和怪字符","");
            }
        }
        if(StringUtil.isNull(zhuji.getAddress())){
            return new ResponseBean(1,1,"主机地址不能为空","");
        }
        if(StringUtil.isNull(zhuji.getPort())){
            return new ResponseBean(1,1,"主机端口不能为空","");
        }
        if(StringUtil.isNull(zhuji.getUid())){
            return new ResponseBean(1,1,"主机用户ID不能为空","");
        }
        if(StringUtil.isNull(zhuji.getOut_id())){
            return new ResponseBean(1,1,"主机额外ID不能为空","");
        }
        if(zhuji.getLianjie_num()==null){
            return new ResponseBean(1,1,"主机最大连接数不能为空","");
        }
        if(StringUtil.isNull(zhuji.getCountry_id())){
            return new ResponseBean(1,1,"所属国家不能为空","");
        }
        if(StringUtil.isNull(zhuji.getArea_id())){
            return new ResponseBean(1,1,"所属区域不能为空","");
        }
        if(zhuji.getLianjie_num() < zhuji2.getSy_lianjie_num()){
            return new ResponseBean(1,1,"最大连接数不能小于已连接数","");
        }
        if(zhuji.getType() == null){
            zhuji.setType(2);
        }
        if (zhujiService.updateById(zhuji)) {
                return new ResponseBean(0, 1, "修改成功","");
        }
        return new ResponseBean(1, 1, "操作失败","");
    }

    /**
     * 删除主机
     * @param id   主机id
     */
    @RequestMapping("/deleteZhuji")
    public ResponseBean delete(String id) {

        if(zhujiService.removeById(id)){
            return new ResponseBean(0,1,"删除成功");
        }
        return new ResponseBean(1,1,"删除失败");
    }

    /**
     * 随机获取主机
     * @param id    主机id
     * @param token 用户请求令牌
     */
    @RequestMapping("/suijigetZhuji")
    public ResponseBean suijigetZhuji(String id,String area_id, @RequestHeader(value = "token" , required = false) String token, HttpServletRequest request, HttpServletResponse response) {

        if(StringUtil.isNull(token)){
            return new ResponseBean(1,1,"请先登录！","");
        }
        try{
            JwtUtil.verifyToken(token) ;
        }catch(Exception e) {
            return new ResponseBean(1,1,"请先登录！","");
        }
        String uid = JwtUtil.getUsername(token);
        AppAdmin appAdmin = appAdminService.getById(uid);
        if(appAdmin != null){
            if(appAdmin.getStatus() == 0) {
                return new ResponseBean(1,1,"用户已禁用","");
            }
            if(appAdmin.getShenyu_time() == null || appAdmin.getShenyu_time()<=0){
                return new ResponseBean(501,1,"您的剩余时长已使用完，请先充值！","");
            }
            //获取ip
//        String ip = IPUtil.getIpAddr(request);
            if(StringUtil.isNull(area_id)){
                return new ResponseBean(1,1,"您未选择地区！","");
            }
//            String config = null;
            QueryWrapper<Zhuji> query = new QueryWrapper();
            query.eq("status",1);
            query.eq("area_id",area_id);
            query.apply("lianjie_num > sy_lianjie_num");
            List<Zhuji> list = zhujiService.list(query);
            if(list.isEmpty()){
                return new ResponseBean(1,1,"没有匹配的主机！","");
            }
            Map<String,Object> map = new HashMap();
            try {
                Map<String,Object> proxy = new HashMap<>();
                Map<String,Object> direct = new HashMap<>();
                List<String> ips=new ArrayList<>();
                List<String> domains=new ArrayList<>();
                List<String> ips2=new ArrayList<>();
                List<String> domains2=new ArrayList<>();
                String pattern = "[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\.?";  //获取纯域名
                String pat = "(\\d*\\.){3}\\d*";      //匹配ip
                Pattern p = Pattern.compile(pattern);
                Pattern p2 = Pattern.compile(pat);
                Matcher m = p.matcher(host);
                String fuwuqi_ip ="";
                if(m.find()){
                    fuwuqi_ip = m.group();
                }
                if(StringUtil.isNotNull(fuwuqi_ip)){
                    Matcher m2 = p2.matcher(fuwuqi_ip);
                    if(m2.find()){ //服务器ip
                        ips2.add(m2.group());
                    }else {  //服务器域名
                        domains2.add(fuwuqi_ip);
                    }
                }
                if("中国".equals(list.get(0).getArea().getCountry().getCountry_zh_name())){   //true:    所选地区国内     ipService.getIpAddress(ip)
                    List<VpnPeizhi> guonei = vpnPeizhiService.list(new QueryWrapper<VpnPeizhi>().eq("type",0));
                    guonei.stream().forEach(n->{
                        if(n.getPd_type().equals(0)){
                            ips.add(n.getIp_address());
                            domains.add(n.getYu_ming());
                            Iterator<String> iterator = domains.iterator();
                            while(iterator.hasNext()) {
                                if(StringUtil.isNull(iterator.next())) {
                                    iterator.remove();
                                }
                            }
                            Iterator<String> iterator2 = ips.iterator();
                            while(iterator2.hasNext()) {
                                if(StringUtil.isNull(iterator2.next())) {
                                    iterator2.remove();
                                }
                            }
                            proxy.put("ip",ips.isEmpty()?null:ips);
                            proxy.put("domain",domains.isEmpty()?null:domains);
                        }else {
                            ips2.add(n.getIp_address());
                            domains2.add(n.getYu_ming());
                            Iterator<String> iterator = ips2.iterator();
                            while(iterator.hasNext()) {
                                if(StringUtil.isNull(iterator.next())) {
                                    iterator.remove();
                                }
                            }
                            Iterator<String> iterator2 = domains2.iterator();
                            while(iterator2.hasNext()) {
                                if(StringUtil.isNull(iterator2.next())) {
                                    iterator2.remove();
                                }
                            }
                            direct.put("ip",ips2.isEmpty()?null:ips2);
                            direct.put("domain",domains2.isEmpty()?null:domains2);
                        }
                    });
                    map.put("direct",direct);
                    map.put("proxy",proxy);
                }else {     //false:   所选地区国外
                    List<VpnPeizhi> guowei = vpnPeizhiService.list(new QueryWrapper<VpnPeizhi>().eq("type",1));
                    guowei.stream().forEach(n->{
                        if(n.getPd_type().equals(0)){
                            ips.add(n.getIp_address());
                            domains.add(n.getYu_ming());
                            Iterator<String> iterator = domains.iterator();
                            while(iterator.hasNext()) {
                                if(StringUtil.isNull(iterator.next())) {
                                    iterator.remove();
                                }
                            }
                            Iterator<String> iterator2 = ips.iterator();
                            while(iterator2.hasNext()) {
                                if(StringUtil.isNull(iterator2.next())) {
                                    iterator2.remove();
                                }
                            }
                            proxy.put("ip",ips.isEmpty()?null:ips);
                            proxy.put("domain",domains.isEmpty()?null:domains);
                        }else {
                            ips2.add(n.getIp_address());
                            domains2.add(n.getYu_ming());
                            Iterator<String> iterator = domains2.iterator();
                            while(iterator.hasNext()) {
                                if(StringUtil.isNull(iterator.next())) {
                                    iterator.remove();
                                }
                            }
                            Iterator<String> iterator2 = ips2.iterator();
                            while(iterator2.hasNext()) {
                                if(StringUtil.isNull(iterator2.next())) {
                                    iterator2.remove();
                                }
                            }
                            direct.put("ip",ips2.isEmpty()?null:ips2);
                            direct.put("domain",domains2.isEmpty()?null:domains2);
                        }
                    });
                    map.put("direct",direct);
                    map.put("proxy",proxy);
                }
            } catch (Exception e) {
                return new ResponseBean(1,1,"国家及地区有误！","");
            }
            Object n = redisTemplate.boundValueOps(appAdmin.getId()).get();
            Zhuji zhuji =null;
            if(n != null){
                if(Integer.parseInt(n.toString()) >= list.size()){
                    redisTemplate.boundValueOps(appAdmin.getId()).set(0);
                    zhuji = list.get(0);
                    map.put("v2rayConfig","vmess://"+DESUtil.getBase64(0,zhuji.toString()));
                    map.put("zhuji_id",zhuji.getId());
                    return new ResponseBean(0,1,"",map);
                }
                zhuji = list.get(Integer.parseInt(n.toString()));
                redisTemplate.boundValueOps(appAdmin.getId()).set(Integer.parseInt(n.toString())+1);
                map.put("v2rayConfig","vmess://"+DESUtil.getBase64(0,zhuji.toString()));
                map.put("zhuji_id",zhuji.getId());
                return new ResponseBean(0,1,"",map);
            }
            redisTemplate.boundValueOps(appAdmin.getId()).set(0);
            zhuji = list.get(0);
            map.put("v2rayConfig","vmess://"+DESUtil.getBase64(0,zhuji.toString()));
            map.put("zhuji_id",zhuji.getId());
            return new ResponseBean(0,1,"",map);
        }else {
            return new ResponseBean(1,1,"请先登录！","");
        }
    }
    /**
     * 主机连接成功后添加使用连接数
     * @param id  主键(主机ID)
     * @param shebei_id  设备ID
     * @param token  用户请求令牌
     * @return
     */
    @RequestMapping("Upzhuji_lianjieNum")
    public ResponseBean Upzhuji_lianjieNum(String id,String shebei_id,@RequestHeader(value = "token" , required = false) String token) throws InterruptedException {

        String uid = JwtUtil.getUsername(token);
        AppAdmin appAdmin = appAdminService.getById(uid);
        if (appAdmin == null){
            return ResponseBean.error("请先登录！") ;
        }
        if(appAdmin.getStatus() == 0) {
            return ResponseBean.error("用户已禁用！") ;
        }
        Zhuji zhuji=zhujiService.getById(id);
        if(zhuji==null){
            return ResponseBean.error("找不到该主机！");
        }
        Object ty = stringRedisTemplate.opsForHash().get("time_"+shebei_id,"type");
        if(ty != null){   //定时更新连接数未执行，重新连接可直接连接
            if(ty.toString().equals(id)){
                return  ResponseBean.OK;
            }else {
                Zhuji redis_zhuji = zhujiService.getById(ty.toString());
                if (redis_zhuji != null && redis_zhuji.getSy_lianjie_num() - 1 >= 0) {
                    redis_zhuji.setSy_lianjie_num(redis_zhuji.getSy_lianjie_num() - 1);
                    if (zhujiService.updateById(redis_zhuji)) {
                        QueryWrapper<Zhuji> queryWrapper = new QueryWrapper();
                        queryWrapper.select("sum(lianjie_num) as lianjie_num,sum(sy_lianjie_num) as sy_lianjie_num");
                        queryWrapper.eq("area_id", redis_zhuji.getArea_id());
                        Zhuji zj = zhujiService.getOne(queryWrapper);
                        if (zj != null && zj.getLianjie_num() > zj.getSy_lianjie_num()) {  //设置地区状态为绿色  未满
                            Area area = areaService.getById(redis_zhuji.getArea_id());
                            area.setStatus(0);
                            areaService.updateById(area);
                        }
                    }
                }
                stringRedisTemplate.opsForHash().put("time_"+shebei_id,"type",id);
            }
        }else {
            stringRedisTemplate.opsForHash().put("time_"+shebei_id,"type",id);
        }
        if(zhuji.getSy_lianjie_num() + 1 > zhuji.getLianjie_num()){
            return ResponseBean.error("该主机连接数已满！");
        }
        zhuji.setSy_lianjie_num(zhuji.getSy_lianjie_num()+1);
        if(zhujiService.updateById(zhuji)){
            QueryWrapper<Zhuji> queryWrapper = new QueryWrapper();
            queryWrapper.select("sum(lianjie_num) as lianjie_num,sum(sy_lianjie_num) as sy_lianjie_num");
            queryWrapper.eq("area_id",zhuji.getArea_id());
            Zhuji zj = zhujiService.getOne(queryWrapper);
            if (zj != null && zj.getLianjie_num().equals(zj.getSy_lianjie_num())){  //设置地区状态为红色  已满
                Area area = areaService.getById(zhuji.getArea_id());
                area.setStatus(1);
                areaService.updateById(area);
            }
            return  ResponseBean.OK;
        }else {
            return  ResponseBean.error("操作失败！");
        }

    }
    /**
     * 主机base码解码
     * @param text  base码
     * @return
     */
    @RequestMapping("zhuan_basema")
    public ResponseBean zhuan_basema(String text){
        if (text.trim().matches("(vmess://)(.*?)")) {
            text.trim().replaceAll("vmess://","");
        }else {
            return new ResponseBean(1,1,"不支持该格式开头！","");
        }
        String basema = DESUtil.getBase64(1,text.trim());
        if(basema.equals("")){
            return new ResponseBean(1,1,"解码失败！",basema);
        }
        return new ResponseBean(0,1,"解码成功！",basema);
    }
}
